import crypto from 'crypto';
import * as $OpenApi from '@alicloud/openapi-client';
import { oauth2_1_0 } from '@alicloud/dingtalk';
import dayjs from 'dayjs';
import log from '@/utils/log';
import {
  appKey,
  appSecret,
  ddKey,
  ddWebhookAccessToken,
  storyPriorityKey,
  storyPriorityWebhookAccessToken,
  techGroupKey,
  techGroupWebhookAccessToken,
  agentId,
  dwFrontKey,
  dwFrontGrouoWebhookAccessToken,
} from '../configs/dingtalk';
import { asyncsendV2, queryDingTalkIdByUserNames, sendToRobot } from './apis';
import { pmUserList } from '../configs/tapd';

const Dingtalkoauth210 = oauth2_1_0.default;
/**
 * Token对象
 */
const currentAccessToken = {
  expired: dayjs('2023-04-18 15:51:00'),
  value: '4c0efdc5dd783c2d8398c7216ef0e887',
};

/**
 * 通知到钉钉群
 * @param key 加密Key
 * @param webhook 调用的勾子链接
 * @param data 传入的数据
 */
async function postToDD(key: string, webhookAccessToken: string, data: any) {
  const timestamp = Date.now();
  const sha = crypto.createHmac('SHA256', key);
  sha.update(`${timestamp}\n${key}`, 'utf8');
  const sign = encodeURI(sha.digest('base64'));
  // 洞窝前端群
  await sendToRobot({ access_token: webhookAccessToken, timestamp, sign }, data);
}

/**
 * 使用 Token 初始化账号Client
 * @return Client
 * @throws Exception
 */
function createClient() {
  const config = new $OpenApi.Config({});
  config.protocol = 'https';
  config.regionId = 'central';
  return new Dingtalkoauth210(config);
}
/**
 * 获取钉钉accessToken
 * @returns Promise<string>
 */
async function getAccessToken(): Promise<string> {
  if (dayjs().diff(currentAccessToken.expired, 'h') < 2) {
    return currentAccessToken.value;
  }
  const client = createClient();
  const getAccessTokenRequest = new oauth2_1_0.GetAccessTokenRequest({
    appKey,
    appSecret,
  });
  // {
  //    "accessToken" : "fw8ef8we8f76e6f7s8dxxxx",
  //    "expireIn" : 7200
  // }
  const ret = await client.getAccessToken(getAccessTokenRequest);
  // TODO: 将accessToken保存到redis中, 默认有效期为7200s.
  currentAccessToken.value = ret.body.accessToken as string;
  currentAccessToken.expired = dayjs();
  return currentAccessToken.value;
}
/**
 * 前端组需求提测，通知到钉钉前端群
 * @param id 需求编号
 * @param title 需求名称
 * @param message 描述
 */
export async function tongzhiFEDD(id: string, title: string, message: string[]) {
  const btns: any[] = [];
  const texts = [title, ...message];
  btns.push({
    title: '查看需求',
    actionURL: `dingtalk://dingtalkclient/page/link?pc_slide=false&url=${encodeURIComponent(`https://www.tapd.cn/41194427/prong/stories/view/${id}`)}`,
  });

  await postToDD(ddKey, ddWebhookAccessToken, {
    msgtype: 'actionCard',
    actionCard: {
      title,
      text: texts.join('\n\n'),
      btns,
    },
  });
}
/**
 * 通知到需求排优先级钉钉群
 * @param id 需求编号
 * @param title 需求名称
 * @param message 描述
 */
export async function noticeToStoryPriorityGroup(id: string, title: string, message: string[]) {
  const btns: any[] = [];
  const texts = [title, ...message];
  btns.push({
    title: '查看需求',
    actionURL: `dingtalk://dingtalkclient/page/link?pc_slide=false&url=${encodeURIComponent(`https://www.tapd.cn/41194427/prong/stories/view/${id}`)}`,
  });

  await postToDD(storyPriorityKey, storyPriorityWebhookAccessToken, {
    msgtype: 'actionCard',
    actionCard: {
      title,
      text: texts.join('\n\n'),
      btns,
    },
  });
}
/**
 * 通知到技术钉钉群
 * @param id 需求编号
 * @param title 需求名称
 * @param message 描述
 */
export async function noticeToTechGroup(id: string, title: string, message: string[]) {
  const btns: any[] = [];
  const texts = [title, ...message];
  btns.push({
    title: '查看需求',
    actionURL: `dingtalk://dingtalkclient/page/link?pc_slide=false&url=${encodeURIComponent(`https://www.tapd.cn/41194427/prong/stories/view/${id}`)}`,
  });

  await postToDD(techGroupKey, techGroupWebhookAccessToken, {
    msgtype: 'actionCard',
    actionCard: {
      title,
      text: texts.join('\n\n'),
      btns,
    },
  });
}
/**
 * 请求钉钉接口
 * @param noticeInfo 消息主体
 * @returns 发送结果
 */
async function toSendBidNoticeMsg(noticeInfo: any) {
  const accessToken: string = await getAccessToken();
  const ret = await asyncsendV2({ access_token: accessToken }, noticeInfo);
  // const ret = await axios.post(`https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2?access_token=${accessToken}`, noticeInfo);
  return ret;
}
/**
 * 生成文本内容，配置技术owner和处理人
 * @param content 描述
 * @param owner 处理人
 * @param techOwner 技术owner
 * @returns string
 */
export function getContent(content: string, owner: string[], techOwner: string[]) {
  const ownerStr = owner && owner.length > 0 ? `当前处理人：${owner.join('、')}` : '';
  const techOwnerStr = techOwner && techOwner.length > 0 ? `技术owner：${techOwner.join('、')}` : '';
  return [content, ownerStr, techOwnerStr].join('\n\n');
}
/**
 * 拼接消息并请求钉钉接口
 * @param storyId 需求ID
 * @param userIds 用户列表
 * @param title 标题
 * @param content 内容
 */
export async function sendMsg(storyId: string, users: string[], title: string, content: string, linkType: 'tasks' | 'stories' = 'stories') {
  let userNames: string[] = [];
  let noUser = false;
  if (!users || users.length <= 0) {
    log.info('需求无数据，请求用户列表：', JSON.stringify(users));
    noUser = true;
    userNames = pmUserList;
  } else {
    userNames = users;
  }
  userNames = userNames.map((t) => t.replace(/\./g, ''));
  const data = await queryDingTalkIdByUserNames({ userNames });
  if (!data || data.length <= 0) {
    log.info('不存在用户', storyId, title);
    return;
  }
  const list = data.map((t: any) => t.dingTalkUserId as string).filter((t) => /^\d+$/.test(t));
  if (list.length <= 0) {
    log.info('不存在用户', storyId, title);
    return;
  }
  const noticeInfo = {
    agent_id: agentId,
    userid_list: list.join(','),
    msg: {
      msgtype: 'action_card',
      action_card: {
        single_title: '查看详情',
        single_url: `dingtalk://dingtalkclient/page/link?pc_slide=false&url=${encodeURIComponent(`https://www.tapd.cn/41194427/prong/${linkType ?? 'stories'}/view/${storyId}`)}`,
        markdown: `## ${title}  \n  ${content}${noUser ? `  \n  未获取处理人` : ''}`,
        title: 'TAPD通知',
      },
    },
  };
  log.info('推送钉钉消息：', JSON.stringify(noticeInfo));
  const ret = await toSendBidNoticeMsg(noticeInfo);
  log.info('推送钉钉消息结果：', JSON.stringify(ret));
}

/**
 * gitlab主分支合并完成发送钉钉消息到前端群
 */
export async function sendMsgMergeDone(title: string, message: string[]) {
  const texts = [title, ...message];
  await postToDD(dwFrontKey, dwFrontGrouoWebhookAccessToken, {
    msgtype: 'actionCard',
    actionCard: {
      title,
      text: texts.join('\n\n'),
    },
  });
}

// 周三上线通知。发送到自己的测试小群
export async function ddSendOnlineStoryMsg(title: string, message: string[]) {
  const texts = [title, ...message];
  // 测试小群
  // 'SEC10aa253d8e48c2b6fabcb1909626fe35203f2c421f1d6e4a09911ae6c290a581', '2807e2a7461907c70d55fdc9bf9b16340fc85058ddcb62893ded19f46a529743'
  await postToDD(dwFrontKey, dwFrontGrouoWebhookAccessToken, {
    msgtype: 'actionCard',
    actionCard: {
      title,
      text: texts.join('\n\n'),
    },
  });
}

// 未合并主分支次数统计
export async function ddSendMergeMasterCountMsg(title: string, message: string[]) {
  // 测试小群
  // 'SEC10aa253d8e48c2b6fabcb1909626fe35203f2c421f1d6e4a09911ae6c290a581', '2807e2a7461907c70d55fdc9bf9b16340fc85058ddcb62893ded19f46a529743'
  await postToDD(dwFrontKey, dwFrontGrouoWebhookAccessToken, {
    msgtype: 'markdown',
    markdown: {
      title: '未合并主分支次数统计',
      text: message.join('\n'),
    },
  });
}

/**
 * 未合并分支钉钉通知
 * @param storyId 需求ID
 * @param userIds 用户列表
 * @param title 标题
 * @param content 内容
 */
export async function sendMsgUnMergeLog(users: string[], title: string, content: string) {
  if (!users || users.length <= 0) {
    return;
  }
  const data = await queryDingTalkIdByUserNames({ userNames: users });
  if (!data || data.length <= 0) {
    return;
  }
  const list = data.map((t: any) => t.dingTalkUserId as string).filter((t) => /^\d+$/.test(t));
  if (list.length <= 0) {
    return;
  }
  const noticeInfo = {
    agent_id: agentId,
    userid_list: list.join(','),
    msg: {
      msgtype: 'action_card',
      action_card: {
        single_title: '查看详情',
        single_url: `dingtalk://dingtalkclient/page/link?pc_slide=false&url=${encodeURIComponent(
          `http://59.110.10.239:8083/funcManage/mergeLogs?author=${users[0]}&createAt=${dayjs().format('YYYY-MM-DD')}`,
        )}`,
        markdown: `## ${title}  \n  ${content}`,
        title: '未合并主分支通知',
      },
    },
  };
  log.info('推送钉钉消息：', JSON.stringify(noticeInfo));
  const ret = await toSendBidNoticeMsg(noticeInfo);
  log.info('推送钉钉消息结果：', JSON.stringify(ret));
}
